export default `<template>
<div class="map-box">
  <div class="map" id="map"></div>
  <div class="btns-box">
    <el-button type="primary" size="small" @click="measure('LineString')">测量</el-button>
    <el-button type="primary" size="small" @click="measure('Polygon')">测面</el-button>
    <el-button type="primary" size="small" @click="clearMeasure">清除测量轨迹</el-button>
  </div>
</div>
</template>

<script>
import "ol/ol.css";
import Draw from "ol/interaction/Draw";
import Map from "ol/Map";
import Overlay from "ol/Overlay";
import View from "ol/View";
import TileArcGISRest from "ol/source/TileArcGISRest";
import { Circle as CircleStyle, Fill, Stroke, Style } from "ol/style";
import { LineString, Polygon } from "ol/geom";
import { OSM, Vector as VectorSource } from "ol/source";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { getArea, getLength } from "ol/sphere";
import { unByKey } from "ol/Observable";

import CONSTANT from "@/config/constant.js";

let layerIndex = 0;

export default {
name: "measureLengthAndArea",

data() {
  return {
    map: null,
    raster: null,
    vector: null,
    sketch: null, //Currently drawn feature
    helpTooltipElement: null, //The help tooltip element.
    helpTooltip: null, //Overlay to show the help messages.
    measureTooltipElement: null, //The measure tooltip element.
    measureTooltip: null, //Overlay to show the measurement.
    // Message to show when the user is drawing a polygon.
    continuePolygonMsg: "Click to continue drawing the polygon",
    // Message to show when the user is drawing a line
    continueLineMsg: "Click to continue drawing the line",
    draw: null, //global so we can remove it later
    listener: null,
    shapeType: null,
    drawCache: {}
  };
},

methods: {
  init() {
    this.vector = new VectorLayer({
      source: new VectorSource(),
      style: new Style({
        fill: new Fill({
          color: "rgba(255, 255, 255, 0.2)"
        }),
        stroke: new Stroke({
          color: "#ffcc33",
          width: 2
        }),
        image: new CircleStyle({
          radius: 7,
          fill: new Fill({
            color: "#ffcc33"
          })
        })
      })
    });

    //初始化地图
    this.map = new Map({
      layers: [
        new TileLayer({
          source: new TileArcGISRest({
            url: CONSTANT.GIS_URL
          })
        }),
        this.vector
      ],
      target: "map",
      view: new View({
        center: [113.0567, 23.67537],
        maxZoom: 18,
        minZoom: 8,
        zoom: 13,
        projection: "EPSG:4326"
      })
    });
  },

  //测距、测面
  measure(type) {
    this.shapeType = type;
    layerIndex++;
    this.drawCache[layerIndex] = {
      feature: null,
      measureTooltip: null
    };
    if (this.draw) {
      this.map.removeInteraction(this.draw);
    }
    // 添加map事件
    this.addMapEvent();
  },

  //清除测量
  clearMeasure() {
    for (let i in this.drawCache) {
      this.map.removeOverlay(this.drawCache[i].measureTooltip);
      this.vector.getSource().removeFeature(this.drawCache[i].feature);
    }
    this.drawCache = {};
    layerIndex = 0;
  },

  addMapEvent() {
    this.map.on("pointermove", evt => {
      this.draw
        ? this.pointerMoveHandler(evt)
        : this.map.removeOverlay(this.helpTooltip);
    });
    this.map.getViewport().addEventListener("mouseout", () => {
      this.helpTooltipElement &&
        this.helpTooltipElement.classList.add("hidden");
    });
    this.addInteraction();
  },

  addInteraction() {
    this.draw = new Draw({
      source: this.vector.getSource(),
      type: this.shapeType,
      style: new Style({
        fill: new Fill({
          color: "rgba(255, 255, 255, 0.2)"
        }),
        stroke: new Stroke({
          color: "rgba(0, 0, 0, 0.5)",
          lineDash: [10, 10],
          width: 2
        }),
        image: new CircleStyle({
          radius: 5,
          stroke: new Stroke({
            color: "rgba(0, 0, 0, 0.7)"
          }),
          fill: new Fill({
            color: "rgba(255, 255, 255, 0.2)"
          })
        })
      })
    });

    this.map.addInteraction(this.draw);
    this.createMeasureTooltip();
    this.createHelpTooltip();
    this.drawHandler();
  },

  /**
   * Handle pointer move.
   * @param {import("../src/ol/MapBrowserEvent").default} evt The event.
   */
  pointerMoveHandler(evt) {
    if (evt.dragging) {
      return;
    }
    /** @type {string} */
    var helpMsg = "Click to start drawing";

    if (this.sketch) {
      var geom = this.sketch.getGeometry();
      if (geom instanceof LineString) {
        helpMsg = this.continueLineMsg;
      }
    }

    this.helpTooltipElement.innerHTML = helpMsg;
    this.helpTooltip.setPosition(evt.coordinate);

    this.helpTooltipElement.classList.remove("hidden");
  },
  /**
   * Format length output.
   * @param {LineString} line The line.
   * @return {string} The formatted length.
   */
  formatLength(line) {
    const sourceProj = this.map.getView().getProjection(); //获取投影坐标系
    var length = getLength(line, { projection: sourceProj });
    var output;
    if (length > 100) {
      output = Math.round((length / 1000) * 100) / 100 + " " + "km";
    } else {
      output = Math.round(length * 100) / 100 + " " + "m";
    }
    return output;
  },

  /**
   * Format area output.
   * @param {Polygon} polygon The polygon.
   * @return {string} Formatted area.
   */
  formatArea(polygon) {
    const sourceProj = this.map.getView().getProjection(); //获取投影坐标系
    const geom = polygon.clone().transform(sourceProj, "EPSG:3857");
    const area = getArea(geom);

    let output;
    if (area > 10000) {
      output =
        Math.round((area / 1000000) * 100) / 100 + " " + "km<sup>2</sup>";
    } else {
      output = Math.round(area * 100) / 100 + " " + "m<sup>2</sup>";
    }
    return output;
  },

  /**
   * Creates a new measure tooltip
   */
  createMeasureTooltip() {
    if (this.measureTooltipElement) {
      this.measureTooltipElement.parentNode.removeChild(
        this.measureTooltipElement
      );
    }
    this.measureTooltipElement = document.createElement("div");
    this.measureTooltipElement.className = "ol-tooltip ol-tooltip-measure";
    this.measureTooltip = new Overlay({
      element: this.measureTooltipElement,
      offset: [0, -15],
      positioning: "bottom-center"
    });
    this.map.addOverlay(this.measureTooltip);
  },

  /**
   * Creates a new help tooltip
   */
  createHelpTooltip() {
    if (this.helpTooltipElement) {
      this.helpTooltipElement.parentNode.removeChild(this.helpTooltipElement);
    }
    this.helpTooltipElement = document.createElement("div");
    this.helpTooltipElement.className = "ol-tooltip hidden";
    this.helpTooltip = new Overlay({
      element: this.helpTooltipElement,
      offset: [15, 0],
      positioning: "center-left"
    });
    this.map.addOverlay(this.helpTooltip);
  },

  drawHandler() {
    this.draw.on("drawstart", evt => {
      this.sketch = evt.feature;
      let tooltipCoord = evt.coordinate;

      this.listener = this.sketch.getGeometry().on("change", evt => {
        let output;
        const geom = evt.target;
        if (geom instanceof LineString) {
          output = this.formatLength(geom);
          tooltipCoord = geom.getLastCoordinate();
        } else if (geom instanceof Polygon) {
          output = this.formatArea(geom);
          tooltipCoord = geom.getInteriorPoint().getCoordinates();
        }
        let closeBtn =
          "<i class='tooltip-close-btn tooltip-close-btn_"+layerIndex+"' data-index='" +
          layerIndex +
          "'>×</i>";
        this.measureTooltipElement.innerHTML = output + closeBtn;
        this.measureTooltip.setPosition(tooltipCoord);
        this.drawCache[layerIndex].measureTooltip = this.measureTooltip;
      });
    });

    this.draw.on("drawend", evt => {
      this.drawCache[layerIndex].feature = evt.feature;

      this.measureTooltipElement.className = "ol-tooltip ol-tooltip-static";
      this.measureTooltip.setOffset([0, -7]);
      // unset sketch
      this.sketch = null;
      // unset tooltip so that a new one can be created
      this.measureTooltipElement = null;
      this.createMeasureTooltip();
      unByKey(this.listener);
      this.map.removeInteraction(this.draw);
      this.draw = null;

      // 删除图层
      const self = this;
      document.querySelector(".tooltip-close-btn_"+layerIndex).addEventListener("click", function() {
        self.vector.getSource().removeFeature(self.drawCache[this.dataset.index].feature)
        self.map.removeOverlay(self.drawCache[this.dataset.index].measureTooltip);
        delete self.drawCache[this.dataset.index]
      });

    });
  }
},

mounted() {
  this.init();
}
};
</script>

<style lang="less" scoped>
.map-box {
height: 100%;
position: relative;
.map {
  height: 100%;
}
.btns-box {
  position: absolute;
  right: 20px;
  top: 20px;
}
}
.map {
/deep/ .ol-tooltip {
  position: relative;
  background: rgba(0, 0, 0, 0.5);
  border-radius: 4px;
  color: white;
  padding: 4px 14px 4px 8px;
  opacity: 0.7;
  white-space: nowrap;
  font-size: 12px;
}
/deep/ .ol-tooltip-measure {
  opacity: 1;
  font-weight: bold;
}
/deep/ .ol-tooltip-static {
  background-color: #ffcc33;
  color: black;
  border: 1px solid white;
}
/deep/ .ol-tooltip-measure:before,
/deep/ .ol-tooltip-static:before {
  border-top: 6px solid rgba(0, 0, 0, 0.5);
  border-right: 6px solid transparent;
  border-left: 6px solid transparent;
  content: "";
  position: absolute;
  bottom: -6px;
  margin-left: -5px;
  left: 50%;
}
/deep/ .ol-tooltip-static:before {
  border-top-color: #ffcc33;
}
//测面、测距的样式
/deep/ .tooltip-close-btn {
  font-style: normal;
  position: absolute;
  color: #2d8cf0;
  right: 0px;
  top: -7px;
  font-weight: bold;
  font-size: 15px;
  cursor: pointer;
  &:hover {
    color: #fff;
  }
}
}
</style>
`